﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SC
{
    public class SocketClient
    {
        //定义接收服务端发送消息的回调
        //private delegate void ReceiveMsgCallBack(string strMsg);
        //声明
        //private ReceiveMsgCallBack receiveCallBack;

        //创建连接的Socket
        public Socket socket;
        //创建接收客户端发送消息的线程
        Thread receiveThread;

        //定义回调
        private delegate void SetTextCallBack(string strValue);
        //声明
        //private SetTextCallBack setCallBack;


        public delegate void RecvEvent(Socket socketSend, MessageType messageType, byte[] data);
        public RecvEvent recvEvent;

        /// <summary>
        /// 添加item
        /// </summary>
        /// <param name="itemData"></param>
        public delegate void ItemAddEvent(Common.TaskItemData itemData);
        public ItemAddEvent itemAddEvent;

        ///// <summary>
        ///// 移除item
        ///// </summary>
        ///// <param name="itemData"></param>
        //public delegate void ItemRemoveEvent(Common.TaskItemData itemData);
        //public ItemRemoveEvent itemRemoveEvent;

        //public delegate void BeginTask(Common.TaskItemData itemData);
        //public BeginTask beginTask;

        //public delegate void EndTask(Common.TaskItemData itemData);
        //public EndTask endTask;


        public delegate void ClientConnect();
        public ClientConnect clientConnect;

        public void ConnectServer(string ip, int port)
        {
            if (socket != null)
            {
                SendHertBeat(null);
            }
            
            if (socket==null || !socket.Connected)
            {
                try
                {
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    System.Net.IPAddress iPAddress = System.Net.IPAddress.Parse(ip);
                    System.Net.IPEndPoint ipEp = new System.Net.IPEndPoint(iPAddress, port);
                    socket.BeginConnect(ipEp, new AsyncCallback(Connect), socket);

                    //接收消息线程
                    receiveThread = new Thread(new ThreadStart(Receive));
                    receiveThread.IsBackground = true;
                    receiveThread.Start();
                    hertBeatTimer = new Timer(SendHertBeat, null, 1000, 1000);
                }
                catch (Exception ex)
                {
                    Common.Log.Error(ex.Message);
                }
            }

        }

        void Connect(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            try
            {
                   client.EndConnect(iar);

            }
            catch (Exception e)
            {
                Common.Log.Error(e.Message);
            }
            finally
            {

            }
            if (socket.Connected)
            {
                Common.Log.Info("重连成功");
                if (clientConnect!=null)
                {
                    clientConnect();
                }
            }
        }

        /// <summary>
        /// 循环接收服务器发送的消息
        /// </summary>
        private void Receive()
        {
            try
            {
                while (!socket.Connected) //等待连接成功
                {
                    System.Threading.Thread.Sleep(1000);
                    Console.WriteLine("!connect");
                }

                Console.WriteLine("connected");
                while (socket.Connected) //等待退出连接
                {
                    byte[] msgType, objBuf;

                    SC.MessagePack.DeserializeObjBuf(socket,out msgType, out objBuf);
                    MessageType messageType = (MessageType)BitConverter.ToInt32(msgType, 0);


                    if (recvEvent != null)
                    {
                        recvEvent(socket, messageType, objBuf);
                    }

                }
            }
            catch (Exception ex)
            {
                Common.Log.Error(ex.Message);
            }
        }



        /// <summary>
        /// 发送消息给服务器
        /// </summary>
        /// <param name="messageType"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public int Send(MessageType messageType,Object str)
        {
            int count = 0;
            if(socket!=null && socket.Connected)
            {
                byte[] buffer;
                buffer = SC.MessagePack.SerializeObject(messageType, str);
                try
                {
                    count = socket.Send(buffer);
                }catch(Exception e)
                {
                    Common.Log.Info("发型消息出错:",e);
                }
            }
            return count;
        }

        public void Close()
        {
            if (socket != null)
            {
                //关闭socket
                socket.Close();

            }
            if (receiveThread != null)
            {
                //终止线程
                receiveThread.Abort();
            }
        }

        public void SendCloseClient()
        {
            if (hertBeatTimer != null)
            {
                hertBeatTimer.Change(-1,-1);
            }
            if(socket!=null && socket.Connected)
            {
                Send(MessageType.CloseClient, socket.LocalEndPoint.ToString());
            }
        }

        private System.Threading.Timer hertBeatTimer;

        

        /// <summary>
        /// 发送心跳包
        /// </summary>
        public void SendHertBeat(object state)
        {
            Send(MessageType.HertBeat,null);
        }

    }
}
